This tutorial will demonstrate how to analyse audio data for acoustic phonetic studies in R. It is mainly intended to demonstrated possible workflows. The topics covered are:
- phonetic databases, the case of
emuR and EMU-SDMS, the EMU Speech Database Management System
- Sample data: the LOD database
- Queries and requeries
- Inscpect the database:
serve()
- Calculate duration for vowel categories
- Vowels formants and visualisations with
ggplot2
- Vowel explorer
- Calculating the Pillai distance
Preamble
This tutorial is organised as an R Markdown notebook. When you execute code within the notebook, the results appear beneath the code. In order to do so, you need to have R and RStudio installed. When this R notebook is loaded into RStudio, you can excecute chunks by clicking the Run button within the chunk or by placing your cursor inside it and pressing Cmd+Shift+Enter, allowing you to experiment with the code. This handout contains all output of the code (tables, visualisations etc.).
The following libraries will be needed and have to be installed.
library(tidyverse)
── Attaching packages ──────────────────────────────────── tidyverse 1.3.0 ──
✓ ggplot2 3.3.0 ✓ purrr 0.3.3
✓ tibble 3.0.0 ✓ dplyr 0.8.99.9002
✓ tidyr 1.0.2 ✓ stringr 1.4.0
✓ readr 1.3.1 ✓ forcats 0.5.0
Warning: package 'tibble' was built under R version 3.6.2
── Conflicts ─────────────────────────────────────── tidyverse_conflicts() ──
x dplyr::filter() masks stats::filter()
x dplyr::lag() masks stats::lag()
library(ggiraph)
library(cowplot)
********************************************************
Note: As of version 1.0.0, cowplot does not change the
default ggplot2 theme anymore. To recover the previous
behavior, execute:
theme_set(theme_cowplot())
********************************************************
library(emuR)
Attaching package: 'emuR'
The following object is masked from 'package:base':
norm
library(tools)
library(rio)
library(ggplot2)
library(magrittr)
Attaching package: 'magrittr'
The following object is masked from 'package:purrr':
set_names
The following object is masked from 'package:tidyr':
extract
library(ggiraph)
library(htmltools)
library(shiny)
library(joeyr, warn.conflicts = FALSE )
This is the "joeyr" package.
library(knitr)
The LOD database
The database contains the audio recordings from the Lëtzebuerger Online Dictionnaire (available here, spoken by one female speaker. The audio files have been automatically segmented with the MAUS tools. We thus have a database conisting of textual data, basically words, and the corresponding audio data. The audio data is segmented into words and phonetic segments (sounds).
This database has been created beforehand. Infos how to create such a database is explained in the EMU-SDMS manual.
We start with loading the database and give an overview of structure and content.
# load database
#db = load_emuDB("/Users/peter.gilles/Documents/_Daten/LOD-emuDB/lod_emuDB")
db = load_emuDB("lod_emuDB")
INFO: Checking if cache needs update for 1 sessions and 539 bundles ...
INFO: Performing precheck and calculating checksums (== MD5 sums) for _annot.json files ...
INFO: Nothing to update!
# display the overview of the structure and content
summary(db)
Name: lod
UUID: c87793c0-012a-11e9-874b-68b599b5deb4
Directory: /Users/peter.gilles/Documents/Data_Science_Humanities/lod_emuDB
Session count: 1
Bundle count: 539
Annotation item count: 10979
Label count: 13547
Link count: 10440
Database configuration:
SSFF track definitions:
name columnName fileExtension
1 dft dft dft
2 praatFms fm praatFms
Level definitions:
name type nrOfAttrDefs attrDefNames
1 bundle ITEM 4 bundle; source; SAM; MAO;
2 ORT ITEM 2 ORT; KAN;
3 MAU SEGMENT 1 MAU;
Link definitions:
type superlevelName sublevelName
1 ONE_TO_MANY bundle ORT
2 ONE_TO_MANY ORT MAU
Tracks in emuR are acoustic representation of the speech signal, here dft for the waveform (time-amplitude representation) and praatFms for the formant measures of vowels (see below).
Levels in an eumR database stand for level of interlinked linguistic information. bundle is the entire audio file, ORT stands for the orthographical representation of the audio file segmented in its single words. MAU is the segmentation of all phonetic segment (=sounds) of all ORT segments in bundle.
The hierarchical structure of these levels is expressed in the link definitions as ONE-TO-MANY.
Database queries
An emuR database can be queried with a powerful query engine. The first example is a simple query for one word, Aarbecht.
sl = query(db, query = "[ ORT == 'Aarbecht']")
sl
The result is a segment list (sl), containing various information about the found item (time, level, name, database info). The result of the query can also be displayed in the EMU Speech Database Management System.
serve(db, seglist = sl)
The GUI will open in the Viewer pane of RStudio or you can open it in a browser (Chrome preferred).

Here we can also display the hiearchical structure for this database item, which is accessed during queries. bundle is the top-level, representing the entire audio file.
The ORT level contains the nodes for the individual words in the bundle, here the two words Aarbecht and Aarbechten. The dependend level then is MAU (=Munich Automatic Unit) representing the single sounds of the words in ORT.

Two aspects render emuR query system extremly powerful: the use of regular expressions (including negation and other extensions) and the combinated query on different levels of the database.
Let’s try more complex queries:
- regular expression, operator
=~, words beginning with Aarbecht...
sl = query(db, query = "[ ORT =~ 'Aarbecht.*']")
sl
Select the vowel [aː] in all words beginning with Aarbecht… Note that in the segment list the label now has changed to the vowel and the respective start-end information is now only for this sound [aː].
sl = query(db, query = "[ ORT =~ 'Aarbecht.*' ^ #MAU=='aː']")
sl
- query all words from
ORT where the MAU level does NOT contain the segments nmɑaːətd.
sl = query(db, query = "[ #ORT =~'.*' ^ MAU !~ '[nmɑaːətd]' ]")
sl
With the query the user can compile the data frame from the database which then forms the subset for the phonetic analysis. We can select e.g. all instances of certain (or all) vowels, specifying the context before or after etc. etc.
Of course, querying for individual segments in the audio file like words or sounds is possible only, if this information has been added to the database before.
Vowel explorer
knitr::include_app("https://petergill.shinyapps.io/shinyplay/")
Calculate the Pillai distance
LS0tCnN1YnRpdGxlOiAiTGVjdHVyZSBmb3IgY2xhc3M6IERhdGEgc2NpZW5jZSBpbiB0aGUgSHVtYW5pdGllcyIKdGl0bGU6ICJCaWcgZGF0YSBpbiB0aGUgYWNvdXN0aWMgcGhvbmV0aWMgYW5hbHlzaXMiCmtuaXQ6IChmdW5jdGlvbihpbnB1dF9maWxlLCBlbmNvZGluZykgewogIG91dF9kaXIgPC0gJ2RvY3MnOwogIHJtYXJrZG93bjo6cmVuZGVyKGlucHV0X2ZpbGUsCiBlbmNvZGluZz1lbmNvZGluZywKIG91dHB1dF9maWxlPWZpbGUucGF0aChkaXJuYW1lKGlucHV0X2ZpbGUpLCBvdXRfZGlyLCAnaW5kZXguaHRtbCcpKX0pCiAKYXV0aG9yOiAiUGV0ZXIgR2lsbGVzIgpkYXRlOiAiMjkuIEFwcmlsIDIwMjAsIDE0aDAwIC0gMTZoMDAsIFVuaXZlcnNpdHkgb2YgTHV4ZW1ib3VyZyIKb3V0cHV0OgogICN0dWZ0ZTo6dHVmdGVfaHRtbDoKICAjdHVmdGU6OnR1ZnRlX2hhbmRvdXQ6IAogIGh0bWxfbm90ZWJvb2s6IAogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDIKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQotLS0KClRoaXMgdHV0b3JpYWwgd2lsbCBkZW1vbnN0cmF0ZSBob3cgdG8gYW5hbHlzZSBhdWRpbyBkYXRhIGZvciBhY291c3RpYyBwaG9uZXRpYyBzdHVkaWVzIGluIFIuIEl0IGlzIG1haW5seSBpbnRlbmRlZCB0byBkZW1vbnN0cmF0ZWQgcG9zc2libGUgd29ya2Zsb3dzLiBUaGUgdG9waWNzIGNvdmVyZWQgYXJlOgoKKiBwaG9uZXRpYyBkYXRhYmFzZXMsIHRoZSBjYXNlIG9mIGBlbXVSYCBhbmQgYEVNVS1TRE1TYCwgdGhlIEVNVSBTcGVlY2ggRGF0YWJhc2UgTWFuYWdlbWVudCBTeXN0ZW0KKiBTYW1wbGUgZGF0YTogdGhlIExPRCBkYXRhYmFzZQoqIFF1ZXJpZXMgYW5kIHJlcXVlcmllcwoqIEluc2NwZWN0IHRoZSBkYXRhYmFzZTogYHNlcnZlKClgCiogQ2FsY3VsYXRlIGR1cmF0aW9uIGZvciB2b3dlbCBjYXRlZ29yaWVzCiogVm93ZWxzIGZvcm1hbnRzIGFuZCB2aXN1YWxpc2F0aW9ucyB3aXRoIGBnZ3Bsb3QyYAoqIFZvd2VsIGV4cGxvcmVyCiogQ2FsY3VsYXRpbmcgdGhlIFBpbGxhaSBkaXN0YW5jZQoKIyBQcmVhbWJsZSB7LX0KClRoaXMgdHV0b3JpYWwgaXMgb3JnYW5pc2VkIGFzICBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgbm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gSW4gb3JkZXIgdG8gZG8gc28sIHlvdSBuZWVkIHRvIGhhdmUgUiBhbmQgUlN0dWRpbyBpbnN0YWxsZWQuIFdoZW4gdGhpcyBSIG5vdGVib29rIGlzIGxvYWRlZCBpbnRvIFJTdHVkaW8sIHlvdSBjYW4gZXhjZWN1dGUgY2h1bmtzIGJ5IGNsaWNraW5nIHRoZSAqUnVuKiBidXR0b24gd2l0aGluIHRoZSBjaHVuayBvciBieSBwbGFjaW5nIHlvdXIgY3Vyc29yIGluc2lkZSBpdCBhbmQgcHJlc3NpbmcgKkNtZCtTaGlmdCtFbnRlciosIGFsbG93aW5nIHlvdSB0byBleHBlcmltZW50IHdpdGggdGhlIGNvZGUuIFRoaXMgaGFuZG91dCBjb250YWlucyBhbGwgb3V0cHV0IG9mIHRoZSBjb2RlICh0YWJsZXMsIHZpc3VhbGlzYXRpb25zIGV0Yy4pLgoKVGhlIGZvbGxvd2luZyBsaWJyYXJpZXMgd2lsbCBiZSBuZWVkZWQgYW5kIGhhdmUgdG8gYmUgaW5zdGFsbGVkLgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZ2dpcmFwaCkKbGlicmFyeShjb3dwbG90KQpsaWJyYXJ5KGVtdVIpCmxpYnJhcnkodG9vbHMpCmxpYnJhcnkocmlvKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkoZ2dpcmFwaCkKbGlicmFyeShodG1sdG9vbHMpCmxpYnJhcnkoc2hpbnkpCmxpYnJhcnkoam9leXIsIHdhcm4uY29uZmxpY3RzID0gRkFMU0UgKQpsaWJyYXJ5KGtuaXRyKQpgYGAKCgojIFRoZSBMT0QgZGF0YWJhc2UKClRoZSBkYXRhYmFzZSBjb250YWlucyB0aGUgYXVkaW8gcmVjb3JkaW5ncyBmcm9tIHRoZSBgTMOrdHplYnVlcmdlciBPbmxpbmUgRGljdGlvbm5haXJlYCAoYXZhaWxhYmxlIFtoZXJlXShodHRwczovL2dpdGh1Yi5jb20vc3BlbGxjaGVja2VyLWx1KSwgc3Bva2VuIGJ5IG9uZSBmZW1hbGUgc3BlYWtlci4gVGhlIGF1ZGlvIGZpbGVzIGhhdmUgYmVlbiBhdXRvbWF0aWNhbGx5IHNlZ21lbnRlZCB3aXRoIHRoZSBbTUFVUyB0b29sc10oaHR0cHM6Ly9jbGFyaW4ucGhvbmV0aWsudW5pLW11ZW5jaGVuLmRlL0JBU1dlYlNlcnZpY2VzL2ludGVyZmFjZSkuIFdlIHRodXMgaGF2ZSBhIGRhdGFiYXNlIGNvbmlzdGluZyBvZiB0ZXh0dWFsIGRhdGEsIGJhc2ljYWxseSB3b3JkcywgYW5kIHRoZSBjb3JyZXNwb25kaW5nIGF1ZGlvIGRhdGEuIFRoZSBhdWRpbyBkYXRhIGlzIHNlZ21lbnRlZCBpbnRvIHdvcmRzIGFuZCBwaG9uZXRpYyBzZWdtZW50cyAoc291bmRzKS4KClRoaXMgZGF0YWJhc2UgaGFzIGJlZW4gY3JlYXRlZCBiZWZvcmVoYW5kLiBJbmZvcyBob3cgdG8gY3JlYXRlIHN1Y2ggYSBkYXRhYmFzZSBpcyBleHBsYWluZWQgaW4gdGhlIFtFTVUtU0RNUyBtYW51YWxdKGh0dHBzOi8vaXBzLWxtdS5naXRodWIuaW8vVGhlLUVNVS1TRE1TLU1hbnVhbC8pLgoKV2Ugc3RhcnQgd2l0aCBsb2FkaW5nIHRoZSBkYXRhYmFzZSBhbmQgZ2l2ZSBhbiBvdmVydmlldyBvZiBzdHJ1Y3R1cmUgYW5kIGNvbnRlbnQuCmBgYHtyfQojIGxvYWQgZGF0YWJhc2UKI2RiID0gbG9hZF9lbXVEQigiL1VzZXJzL3BldGVyLmdpbGxlcy9Eb2N1bWVudHMvX0RhdGVuL0xPRC1lbXVEQi9sb2RfZW11REIiKQpkYiA9IGxvYWRfZW11REIoImxvZF9lbXVEQiIpCgojIGRpc3BsYXkgdGhlIG92ZXJ2aWV3IG9mIHRoZSBzdHJ1Y3R1cmUgYW5kIGNvbnRlbnQKc3VtbWFyeShkYikKCmBgYAoKVHJhY2tzIGluIGBlbXVSYCBhcmUgYWNvdXN0aWMgcmVwcmVzZW50YXRpb24gb2YgdGhlIHNwZWVjaCBzaWduYWwsIGhlcmUgYGRmdGAgZm9yIHRoZSB3YXZlZm9ybSAodGltZS1hbXBsaXR1ZGUgcmVwcmVzZW50YXRpb24pIGFuZCBgcHJhYXRGbXNgIGZvciB0aGUgZm9ybWFudCBtZWFzdXJlcyBvZiB2b3dlbHMgKHNlZSBiZWxvdykuIAoKTGV2ZWxzIGluIGFuIGBldW1SYCBkYXRhYmFzZSBzdGFuZCBmb3IgbGV2ZWwgb2YgaW50ZXJsaW5rZWQgbGluZ3Vpc3RpYyBpbmZvcm1hdGlvbi4gYGJ1bmRsZWAgaXMgdGhlIGVudGlyZSBhdWRpbyBmaWxlLCBgT1JUYCBzdGFuZHMgZm9yIHRoZSBvcnRob2dyYXBoaWNhbCByZXByZXNlbnRhdGlvbiBvZiB0aGUgYXVkaW8gZmlsZSBzZWdtZW50ZWQgaW4gaXRzIHNpbmdsZSB3b3Jkcy4gYE1BVWAgaXMgdGhlIHNlZ21lbnRhdGlvbiBvZiBhbGwgcGhvbmV0aWMgc2VnbWVudCAoPXNvdW5kcykgb2YgYWxsIGBPUlRgIHNlZ21lbnRzIGluIGBidW5kbGVgLgoKVGhlIGhpZXJhcmNoaWNhbCBzdHJ1Y3R1cmUgb2YgdGhlc2UgbGV2ZWxzIGlzIGV4cHJlc3NlZCBpbiB0aGUgYGxpbmsgZGVmaW5pdGlvbnNgIGFzIGBPTkUtVE8tTUFOWWAuCgoKCiMgRGF0YWJhc2UgcXVlcmllcwoKQW4gZW11UiBkYXRhYmFzZSBjYW4gYmUgcXVlcmllZCB3aXRoIGEgcG93ZXJmdWwgcXVlcnkgZW5naW5lLiBUaGUgZmlyc3QgZXhhbXBsZSBpcyBhIHNpbXBsZSBxdWVyeSBmb3Igb25lIHdvcmQsIGBBYXJiZWNodGAuCgpgYGB7cn0Kc2wgPSBxdWVyeShkYiwgcXVlcnkgPSAiWyBPUlQgPT0gJ0FhcmJlY2h0J10iKQpzbApgYGAKClRoZSByZXN1bHQgaXMgYSBgc2VnbWVudCBsaXN0YCAoYHNsYCksIGNvbnRhaW5pbmcgdmFyaW91cyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZm91bmQgaXRlbSAodGltZSwgbGV2ZWwsIG5hbWUsIGRhdGFiYXNlIGluZm8pLiBUaGUgcmVzdWx0IG9mIHRoZSBxdWVyeSBjYW4gYWxzbyBiZSBkaXNwbGF5ZWQgaW4gdGhlIEVNVSBTcGVlY2ggRGF0YWJhc2UgTWFuYWdlbWVudCBTeXN0ZW0uIAoKYHNlcnZlKGRiLCBzZWdsaXN0ID0gc2wpYAoKVGhlIEdVSSB3aWxsIG9wZW4gaW4gdGhlIGBWaWV3ZXJgIHBhbmUgb2YgUlN0dWRpbyBvciB5b3UgY2FuIG9wZW4gaXQgaW4gYSBicm93c2VyIChDaHJvbWUgcHJlZmVycmVkKS4KCmBgYHtyIGVjaG89RkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKHJlcCgiZW11LXNkbXMucG5nIikpCmBgYAoKSGVyZSB3ZSBjYW4gYWxzbyBkaXNwbGF5IHRoZSBoaWVhcmNoaWNhbCBzdHJ1Y3R1cmUgZm9yIHRoaXMgZGF0YWJhc2UgaXRlbSwgd2hpY2ggaXMgYWNjZXNzZWQgZHVyaW5nIHF1ZXJpZXMuIGBidW5kbGVgIGlzIHRoZSB0b3AtbGV2ZWwsIHJlcHJlc2VudGluZyB0aGUgZW50aXJlIGF1ZGlvIGZpbGUuIAoKVGhlIGBPUlRgIGxldmVsIGNvbnRhaW5zIHRoZSBub2RlcyBmb3IgdGhlIGluZGl2aWR1YWwgd29yZHMgaW4gdGhlIGBidW5kbGVgLCBoZXJlIHRoZSB0d28gd29yZHMgYEFhcmJlY2h0YCBhbmQgYEFhcmJlY2h0ZW5gLiBUaGUgZGVwZW5kZW5kIGxldmVsIHRoZW4gaXMgYE1BVWAgKD1gTXVuaWNoIEF1dG9tYXRpYyBVbml0YCkgcmVwcmVzZW50aW5nIHRoZSBzaW5nbGUgc291bmRzIG9mIHRoZSB3b3JkcyBpbiBgT1JUYC4gCgpgYGB7ciBlY2hvPUZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhyZXAoImhpZXJhcmNoeS5wbmciKSkKYGBgCgpUd28gYXNwZWN0cyByZW5kZXIgZW11UiBxdWVyeSBzeXN0ZW0gZXh0cmVtbHkgcG93ZXJmdWw6IHRoZSB1c2Ugb2YgcmVndWxhciBleHByZXNzaW9ucyAoaW5jbHVkaW5nIG5lZ2F0aW9uIGFuZCBvdGhlciBleHRlbnNpb25zKSBhbmQgdGhlIGNvbWJpbmF0ZWQgcXVlcnkgb24gZGlmZmVyZW50IGxldmVscyBvZiB0aGUgZGF0YWJhc2UuCgpMZXQncyB0cnkgbW9yZSBjb21wbGV4IHF1ZXJpZXM6CgotIHJlZ3VsYXIgZXhwcmVzc2lvbiwgb3BlcmF0b3IgYD1+YCwgd29yZHMgYmVnaW5uaW5nIHdpdGggYEFhcmJlY2h0Li4uYApgYGB7cn0Kc2wgPSBxdWVyeShkYiwgcXVlcnkgPSAiWyBPUlQgPX4gJ0FhcmJlY2h0LionXSIpCnNsCmBgYAoKU2VsZWN0IHRoZSB2b3dlbCBbYcuQXSBpbiBhbGwgd29yZHMgYmVnaW5uaW5nIHdpdGggYEFhcmJlY2h0YC4uLiBOb3RlIHRoYXQgaW4gdGhlIHNlZ21lbnQgbGlzdCB0aGUgbGFiZWwgbm93IGhhcyBjaGFuZ2VkIHRvIHRoZSB2b3dlbCBhbmQgdGhlIHJlc3BlY3RpdmUgc3RhcnQtZW5kIGluZm9ybWF0aW9uIGlzIG5vdyBvbmx5IGZvciB0aGlzIHNvdW5kIFthy5BdLgoKYGBge3J9CnNsID0gcXVlcnkoZGIsIHF1ZXJ5ID0gIlsgT1JUID1+ICdBYXJiZWNodC4qJyBeICNNQVU9PSdhy5AnXSIpCnNsCgpgYGAKCi0gcXVlcnkgYWxsIHdvcmRzIGZyb20gYE9SVGAgd2hlcmUgdGhlIGBNQVVgIGxldmVsIGRvZXMgTk9UIGNvbnRhaW4gdGhlIHNlZ21lbnRzIGBubcmRYcuQyZl0ZGAuCgpgYGB7cn0Kc2wgPSBxdWVyeShkYiwgcXVlcnkgPSAiWyAjT1JUID1+Jy4qJyBeIE1BVSAhfiAnW25tyZFhy5DJmXRkXScgXSIpCnNsCgpgYGAKCldpdGggdGhlIHF1ZXJ5IHRoZSB1c2VyIGNhbiBjb21waWxlIHRoZSBkYXRhIGZyYW1lIGZyb20gdGhlIGRhdGFiYXNlIHdoaWNoIHRoZW4gZm9ybXMgdGhlIHN1YnNldCBmb3IgdGhlIHBob25ldGljIGFuYWx5c2lzLiBXZSBjYW4gc2VsZWN0IGUuZy4gYWxsIGluc3RhbmNlcyBvZiBjZXJ0YWluIChvciBhbGwpIHZvd2Vscywgc3BlY2lmeWluZyB0aGUgY29udGV4dCBiZWZvcmUgb3IgYWZ0ZXIgZXRjLiBldGMuCgpPZiBjb3Vyc2UsIHF1ZXJ5aW5nIGZvciBpbmRpdmlkdWFsIHNlZ21lbnRzIGluIHRoZSBhdWRpbyBmaWxlIGxpa2Ugd29yZHMgb3Igc291bmRzIGlzIHBvc3NpYmxlIG9ubHksIGlmIHRoaXMgaW5mb3JtYXRpb24gaGFzIGJlZW4gYWRkZWQgdG8gdGhlIGRhdGFiYXNlIGJlZm9yZS4KCgojIFZvd2VsIGV4cGxvcmVyCmBgYHtyfQprbml0cjo6aW5jbHVkZV9hcHAoImh0dHBzOi8vcGV0ZXJnaWxsLnNoaW55YXBwcy5pby9zaGlueXBsYXkvIikKYGBgCgojIENhbGN1bGF0ZSB0aGUgUGlsbGFpIGRpc3RhbmNlCgojIyBmcm9tIGh0dHBzOi8vam9leXN0YW5sZXkuY29tL2Jsb2cvYS10dXRvcmlhbC1pbi1jYWxjdWxhdGluZy12b3dlbC1vdmVybGFwCgpgYGB7ciBlY2hvPUZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhyZXAoImh0dHBzOi8vam9leXN0YW5sZXkuY29tL2ltYWdlcy9wbG90cy9vdmVybGFwX3R1dG9yaWFsL3BpbGxhaV9leGFtcGxlLnBuZyIpKQoKCmBgYAoKCgo=